package com.example.process;
import java.util.*;

// 多级反馈队列调度器实现(带调试输出)
class MLFQScheduler {
    private final Queue<PCB>[] readyQueues = new LinkedList[3];
    private final Queue<PCB> blockedQueue = new LinkedList<>();
    private PCB currentProcess;
    private boolean isExecuting = false;
    private int timeStep = 0; // 添加时间步计数器

    public MLFQScheduler() {
        for (int i = 0; i < 3; i++) {
            readyQueues[i] = new LinkedList<>();
        }
        System.out.println("MLFQ调度器初始化完成，创建了3级就绪队列");
    }

    public void addProcess(PCB process) {
        if (!isProcessInAnyQueue(process)) {
            readyQueues[0].add(process);
            process.state = "就绪";
            System.out.printf("时间步 %d: 添加新进程 %s 到最高优先级队列(0级)\n",
                    timeStep, process.id);
            printQueuesStatus();
        } else {
            System.out.printf("时间步 %d: 进程 %s 已在队列中，添加操作被忽略\n",
                    timeStep, process.id);
        }
    }

    public void scheduleStep() {
        timeStep++;
        System.out.printf("\n=== 时间步 %d 开始 ===\n", timeStep);

        // 处理当前执行进程
        if (currentProcess != null && currentProcess.state.equals("执行中")) {
            System.out.printf("处理当前执行进程 %s 的完成情况\n", currentProcess.id);
            handleCurrentProcessCompletion();
        }

        currentProcess = null;
        isExecuting = false;

        // 从高到低优先级查找可执行进程
        for (int level = 0; level < 3; level++) {
            if (!readyQueues[level].isEmpty()) {
                currentProcess = readyQueues[level].poll();
                currentProcess.state = "执行中";
                isExecuting = true;
                System.out.printf("从队列 %d 选择进程 %s 执行\n",
                        level, currentProcess.id);
                executeProcess(currentProcess, level);
                break;
            }
        }

        if (currentProcess == null) {
            System.out.println("没有可执行的进程，所有队列为空");
        }

        unblockProcesses();
        printQueuesStatus();
        System.out.printf("=== 时间步 %d 结束 ===\n", timeStep);
    }

    private void executeProcess(PCB process, int currentLevel) {
        if (isExecuting) {
            int timeQuantum = getTimeQuantum(currentLevel);
            int timeUsed = Math.min(process.remainingTime, timeQuantum);
            process.remainingTime -= timeUsed;

            System.out.printf("进程 %s 在队列 %d 执行了 %d 单位时间 (时间片: %d), 剩余时间: %d\n",
                    process.id, currentLevel, timeUsed,
                    timeQuantum, process.remainingTime);

            if (process.remainingTime > 0) {
                // 50%概率模拟I/O阻塞
                if (Math.random() < 0.2) {
                    process.state = "阻塞";
                    process.remainingTime += timeUsed;
                    blockedQueue.add(process);
                    System.out.printf("进程 %s 进入阻塞状态 (I/O等待)\n", process.id);
                } else {
                    // 直接降级到下一级队列
                    int nextLevel = Math.min(currentLevel + 1, 2);
                    process.state = "就绪";
                    readyQueues[nextLevel].add(process);
                    System.out.printf("进程 %s 降级到队列 %d\n",
                            process.id, nextLevel);
                }
            } else {
                process.state = "完成";
                System.out.printf("进程 %s 已完成\n", process.id);
            }
        }
    }

    private void handleCurrentProcessCompletion() {
        if (currentProcess == null) return;

        if (currentProcess.remainingTime <= 0) {
            currentProcess.state = "完成";
            System.out.printf("进程 %s 已完成\n", currentProcess.id);
        } else if ("执行中".equals(currentProcess.state)) {
            currentProcess.state = "就绪";
            int nextLevel = 1;
            readyQueues[nextLevel].add(currentProcess);
            System.out.printf("进程 %s 从执行状态降级到队列 %d\n",
                    currentProcess.id, nextLevel);
        }
    }

    // 打印所有队列的当前状态
    private void printQueuesStatus() {
        System.out.println("\n当前队列状态:");
        for (int i = 0; i < 3; i++) {
            System.out.printf("队列 %d (优先级 %s): %s\n",
                    i,
                    i == 0 ? "高" : (i == 1 ? "中" : "低"),
                    getQueueContents(readyQueues[i]));
        }
        System.out.printf("阻塞队列: %s\n", getQueueContents(blockedQueue));
        System.out.printf("当前执行进程: %s\n\n",
                currentProcess != null ? currentProcess.id : "无");
    }

    // 辅助方法：获取队列内容字符串
    private String getQueueContents(Queue<PCB> queue) {
        if (queue.isEmpty()) return "空";

        StringBuilder sb = new StringBuilder();
        for (PCB p : queue) {
            sb.append(p.id).append("(").append(p.remainingTime).append(") ");
        }
        return sb.toString().trim();
    }

    private void unblockProcesses() {
        List<PCB> toUnblock = new ArrayList<>();
        blockedQueue.forEach(p -> {
            if (Math.random() < 0.6) {
                toUnblock.add(p);
            }
        });

        if (!toUnblock.isEmpty()) {
            System.out.println("\n解除阻塞的进程:");
            toUnblock.forEach(p -> {
                p.state = "就绪";
                readyQueues[0].add(p);
                blockedQueue.remove(p);
                System.out.printf("进程 %s 从阻塞状态恢复，加入队列 0\n", p.id);
            });
        }
    }

    // 以下方法保持不变...
    private int getCurrentQueueLevel(PCB process) {
        for (int level = 0; level < 3; level++) {
            if (readyQueues[level].contains(process)) {
                return level;
            }
        }
        return -1;
    }

    private boolean isProcessInAnyQueue(PCB process) {
        for (Queue<PCB> queue : readyQueues) {
            if (queue.contains(process)) {
                return true;
            }
        }
        return blockedQueue.contains(process);
    }

    private int getTimeQuantum(int level) {
        return new int[]{4, 6, 8}[level];
    }

    public Queue<PCB> getReadyQueue(int level) {
        return readyQueues[level];
    }

    public Queue<PCB> getBlockedQueue() {
        return blockedQueue;
    }

    public PCB getCurrentProcess() {
        return currentProcess;
    }
}